package com.cskaoyan.javase.oop1._13block._2building;

/**
 * 构造代码块
 * 指的是声明在类的成员位置,使用以下语法声明的代码块:
 * // 成员位置
 * {
 *
 * }
 * // 成员位置
 * 作用: 随着构造器的执行而执行
 *      和构造器的作用一样,用来在创建对象的过程中给成员变量赋值
 *  注:
 *      构造器当中可以使用this关键字访问成员变量/方法
 *      构造代码块当中也可以,构造代码块中也有this关键字
 *      但是构造代码块当中不能用this表示调用构造器
 *
 * 总结一下目前为止,学习的给对象的成员变量赋值的手段(在创建对象过程中):
 *      1.默认初始化具有默认值
 *      2.构造器赋值
 *      3.显式赋值
 *      4.构造代码块赋值
 * 以上赋值方式,默认初始化最先进行,构造器赋值最后进行
 * 而显式赋值和构造代码块赋值,是按照代码的书写顺序从上往下执行的.
 *
 * 思考:
 *      为什么显式赋值和构造代码块赋值,是按照代码的书写顺序从上往下执行的呢?
 *      而且把构造代码块赋值写在显式赋值的上面,从语法上来说也有点奇怪,好像成员变量还没有声明定义,就赋值了
 *      所以这都是为什么呢?
 *
 * 通过查看反编译文件代码,我们发现:
 *      编译后的class文件中,是不存在构造代码块的结构的
 *      编译器会把构造代码块中的赋值语句和显式赋值的语句,智能地加入类中的每一个构造器的前几行
 *      解释:
 *          何为智能地?
 *          智能是为了保证,显式赋值和构造代码块赋值按照代码的书写顺序从上到下执行
 *              因为放入构造器中的赋值语句,在后面执行
 *          反编译后的代码中仅存在显式赋值和构造器赋值
 *
 *          构造代码块中的代码会放入类中的每一个构造器中(假如这个语句不是赋值语句)
 *          这说明只要使用一次构造器new对象,那么构造代码块就会执行一次,不管用哪个构造器!
 *
 *          构造代码块中的代码会加入构造器的前几行
 *          这是为了保证构造代码块中的语句一定在构造器之前执行
 *
 * 构造代码块最重要的特点就是:
 *      类中的构造代码块无论执行哪个构造器.都会随之执行一次.
 *      构造代码块的经典用途:"提取公因式"
 *      将每一个构造器中都需要执行的代码,放入构造代码块中
 *
 * @since 14:52
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*Student s = new Student(18);
        System.out.println(s.age);*/

        /*Student s = new Student();
        System.out.println(s.age);*/

        for (int i = 0; i < 5; i++) {
            new Student(18);
        }

        Student s2 = new Student();
    }
}

class Student {

    // 构造代码块
    {
        age = 28;
        System.out.println("hello world!");
    }

    int age = 19;
    String name;

    public Student(int age, String name) {
        System.out.println("双参");
        this.age = age;
        this.name = name;
    }

    public Student() {
        System.out.println("无参");
    }

    public Student(int age) {
        System.out.println("单参");
        this.age = age;
    }
}